﻿/*
题目: 生命游戏

根据 百度百科 ， 生命游戏 ，简称为 生命 ，是英国数学家约翰·何顿·康威在 1970 年发明的细胞自动机。

给定一个包含 m × n 个格子的面板，每一个格子都可以看成是一个细胞。每个细胞都具有一个初始状态： 1 即为 活细胞 （live），或 0 即为 死细胞 （dead）。每个细胞与其八个相邻位置（水平，垂直，对角线）的细胞都遵循以下四条生存定律：

如果活细胞周围八个位置的活细胞数少于两个，则该位置活细胞死亡；
如果活细胞周围八个位置有两个或三个活细胞，则该位置活细胞仍然存活；
如果活细胞周围八个位置有超过三个活细胞，则该位置活细胞死亡；
如果死细胞周围正好有三个活细胞，则该位置死细胞复活；
下一个状态是通过将上述规则同时应用于当前状态下的每个细胞所形成的，其中细胞的出生和死亡是同时发生的。给你 m x n 网格面板 board 的当前状态，返回下一个状态。

https://leetcode.cn/problems/game-of-life/?envType=study-plan-v2&envId=2024-spring-sprint-100
*/

#include <iostream>
#include <random>
#include <string>
#include <vector>
#include <list>
#include "TreeNode.hpp"
#include "ListNode.hpp"
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <algorithm>
#include <functional>

using namespace std;

class Solution {
public:
    static constexpr int live2dead = (1 << 1);
    static constexpr int dead2live = (1 << 2);
    static constexpr int keep = (1 << 3);

    // 周围一圈的坐标
    int arround[8][2] = { {0, 1}, {0, -1}, {1, 0}, {-1, 0}, {-1, 1}, {-1, -1}, {1, -1}, {1, 1} };

    int n, m;
    void gameOfLife(vector<vector<int>>& board) {
        n = board.size(), m = board[0].size();

        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                int live = 0;
                for (int* dir : arround) {
                    int x = i + dir[0];
                    int y = j + dir[1];

                    if (ok(x, y) && (board[x][y] & 1) == 1) {
                        live++;
                    }
                }

                board[i][j] |= next_state(board[i][j] & 1, live);
                printf("%b|%d   ", board[i][j], live);
            }
            std::cout << std::endl;
        }

        // 状态更新
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                board[i][j] = update(board[i][j]);
            }
        }
    }

    int next_state(int cur, int live) {
        if (cur == 1 && !(live == 2 || live == 3))
            return live2dead;
        else if (cur == 0 && live == 3)
            return dead2live;
        return keep;
    }

    int update(int state) {
        if ((state)&keep)     return state & 1;
        else if (state & dead2live)     return 1;
        else if (state & live2dead)     return 0;
        return 999;
    }

    bool ok(int x, int y) {
        return x >= 0 && x < n&& y >= 0 && y < m;
    }
};
